package club.emergency.wechat.interceptor.impl;

import club.emergency.wechat.common.response.ResponseEntity;
import club.emergency.wechat.common.response.StatusCode;
import club.emergency.wechat.sso.jwt.JwtTokenUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Create with IntelliJ IDEA
 * Project Name: wecaht
 * Package Name: club.emergency.wechat.interceptor.impl
 * Date: 2018/12/4
 *
 * @author: 快乐的小菌菌
 * Description:
 */
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Value("${jwt.secretKey}")
    private String secretKey;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        String authorization = request.getHeader("Authorization");
        ServletOutputStream outputStream = response.getOutputStream();
        try {
            Claims claims = JwtTokenUtil.parseJWT(secretKey, authorization);
            //获取subject，由于staff的详细信息只有在login接口中存在，并且login接口已在interceptor经被排除，所以这里的subject只有“refreshToken”和“accessToken”两种字符串。
            String subject = claims.getSubject();
            /* 针对refreshToken做相应处理，因为使用refreshToken一定是因为在accessToken失效的情况下。又因为涉及到accessToken更新
             * 问题，所以在使用refreshToken的时候要提示前台需要从新获取两token。
             * 在使用refreshToken请求的时候需要更新两token（accessToken、refreshToken）
             */
            if ("refreshToken".equals(subject)) {
                /**
                 * 这行判断是因为更新token接口必须要带着refreshToken，不可以在interceptor中排除该接口地址，
                 * 这样的话会有接口安全问题产生，在这里return true就可以放行updateToken接口以便前台更新token
                 */
                if ("/manager-search/updateToken".equals(request.getServletPath())) {
                    return true;
                }
                if ("/staff-search/updateToken".equals(request.getServletPath())) {
                    return true;
                }
                outputStream.print(ResponseEntity.error(StatusCode.AUTHORIZATION_EXPIRED, "please use accessToken to invoke this api"));
                outputStream.close();
            }
            return true;
        } catch (ExpiredJwtException e) {
            outputStream.print(ResponseEntity.error(StatusCode.AUTHORIZATION_EXPIRED, "authorization_expired"));
            outputStream.close();
            return false;
        } catch (SignatureException e) {
            outputStream.print(ResponseEntity.error(StatusCode.AUTHORIZATION_EXPIRED, "authorization_illage"));
            outputStream.close();
            return false;
        }
    }

}
